package com.village.friend.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.village.friend.constant.PolicyType;
import com.village.friend.dto.request.AppUserProfitQueryDto;
import com.village.friend.entity.*;
import com.village.friend.mapper.AppUserProfitMapper;
import com.village.friend.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.village.friend.utils.InviteUtils;
import com.village.friend.utils.ParamUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.beans.ConstructorProperties;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 用户收益明细表 服务实现类
 * </p>
 *
 * @author yl
 * @since 2021-08-23
 */

@Service
@Slf4j
public class AppUserProfitServiceImpl extends ServiceImpl<AppUserProfitMapper, AppUserProfit> implements AppUserProfitService {

    @Autowired
    private UserService userService;
    @Autowired
    private AppUserMappingService mappingService;
    @Autowired
    private AppProfitPolicyService profitPolicyService;
    @Autowired
    private AppUserAccountService accountService;
    @Autowired
    private AppUserProfitService profitService;

    @Override
    public IPage<AppUserProfit> pageByParam(AppUserProfitQueryDto param) {
        IPage<AppUserProfit> page = new Page<>(param.getPage(),param.getLimit());
        QueryWrapper<AppUserProfit> qw = new QueryWrapper<>();
        if(StringUtils.isNotBlank(param.getOrderNo())){
            qw.eq("order_no",param.getOrderNo());
        }
        if(StringUtils.isNotBlank(param.getProfitType())){
            qw.eq("profit_type",param.getProfitType());
        }
        if(StringUtils.isNotBlank(param.getTransUser())){
            qw.eq("trans_user_id",param.getTransUser());
        }
        if(StringUtils.isNotBlank(param.getUser())){
            qw.eq("user_id",param.getUser());
        }
        return page(page,qw);
    }

    @Override
    public List<AppUserProfit> findByOrderNo(String oderNo) {
        QueryWrapper<AppUserProfit> qw = new QueryWrapper<>();
        qw.eq("order_no",oderNo);
        return list(qw);
    }

    @Transactional
    public void saveMemberProfit(AppPaymentOrder order){
        // 查询交易是否成功
        if (!order.getPayStatus().equals("SUCCESS")) {
            log.info("本次交易不成功！不记录！");
            return;
        }
        // 510X_
        String payTypeNO = order.getPayTypeNo();
        PolicyType businessType = PolicyType.valueTrans(payTypeNO);
        if(businessType == PolicyType.UNKNOW){
            log.info(businessType.getName() + "类型,不分润");
            return;
        }

        // 已经算过分润的就不算了
        {
            List<AppUserProfit> profits = findByOrderNo(order.getId());
            if (profits != null && profits.size() > 0) {
                log.warn("交易已分润");
                return;
            }
        }
        log.info("Order信息: " + JSONObject.toJSONString(order));

        // 订单额
        BigDecimal orderAmount = order.getOrderAmount();
        log.info("Order金额: " + orderAmount);

        // 交易的人：C
        User userC = userService.findByUsername(order.getUserId());
        log.info("userC:" + JSONObject.toJSONString(userC));

        // 交易会员级别
        int userGrade = userC.getVipLevel();
        log.info("userC级别：" + userGrade);


        //获取用户分润配置
        AppProfitPolicy profitPolicy = profitPolicyService.findByGroupAndKey(order.getPayTypeNo(), userC.getVipLevel() + "");
        List<ColValueBean> profitList = profitPolicy.transKey2String();
        if(profitList == null || profitList.isEmpty()){
            throw new RuntimeException("未配置分润信息!!");
        }
        if(!ParamUtils.checkProfit(profitList)){
            throw new RuntimeException("分润配置异常,比例配置过高或小于0!!");
        }


        //获取上级信息
        List<AppUserMapping> parentUsers = mappingService.findParentUsers(userC.getUsername());
        Map<Integer, String> parentMap = ParamUtils.parentMapping2Map(parentUsers);

        List<User> parents = userService.listIn(parentMap.values());
        Map<String, User> userMap = ParamUtils.user2Map(parents);

        //生成分润信息
        Map<String,Integer> profitPercentMap = new HashMap<>();
        Map<String,PercentAndProfitBean> profitMap = genProfitInfo(order.getOrderAmount(),profitList,parentMap,userMap);

        //持久化
        if(!profitMap.isEmpty()){
            for (String key : profitMap.keySet()) {
                PercentAndProfitBean profit = profitMap.get(key);
                User user = userMap.get(key);
                insertProfitAndUpdateBalance(user,userC,order.getPayTypeNo(),order.getId(),BigDecimal.valueOf(profit.getPrecnet()),profit.getProfit(),orderAmount,"");
            }
        }

    }


    /**
     * 插入分润信息 并更新余额
     * @param profitUser 分润用户
     * @param user 交易用户
     * @param profitType 分润类型
     * @param merchantOrderNo 代理商订单id
     * @param percent 分润比例
     * @param profit 分润金额
     * @param orderAmount 交易金额
     * @param remark 描述
     */
    private void insertProfitAndUpdateBalance(User profitUser, User user, String profitType, String merchantOrderNo
            , BigDecimal percent, BigDecimal profit, BigDecimal orderAmount, String remark){
        AppUserProfit memberProfit = new AppUserProfit();
        memberProfit.setId(InviteUtils.get32UUID());
        memberProfit.setUserId(profitUser.getUsername());
        memberProfit.setFullName(profitUser.getNickname());
        memberProfit.setTransUserId(user.getUsername());
        memberProfit.setTransFullName(user.getNickname());
        memberProfit.setTransAmount(orderAmount);
        memberProfit.setOrderNo(merchantOrderNo);
        memberProfit.setUserProfit(profit);
        memberProfit.setProfitPercent(percent);
        memberProfit.setProfitType(profitType);
        memberProfit.setRemark(remark);
//        if(profit.compareTo(BigDecimal.valueOf(0.00)) <= 0){
//            log.info(remark + ": 金额小于等于0不进行分润插入和余额更新," + profit);
//            return;
//        }
        profitService.save(memberProfit);
        log.info("插入" + remark + "：" + JSONObject.toJSONString(memberProfit));

        addBlance(profitUser.getUsername(), profit);
    }

    /**
     * 增加用户的余额
     *
     * @param profit
     */
    private void addBlance(String userId, BigDecimal profit) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("userId", userId);
        AppUserAccount memberAccount = accountService.findByUserId(userId);
        if (memberAccount != null) {
            log.info("获取用户[" + userId + "] = 的账户数据为：" + JSONObject.toJSONString(memberAccount));
            BigDecimal newBalance = memberAccount.getBalance().add(profit);
            BigDecimal newProfit = memberAccount.getTotalProfit().add(profit);
            memberAccount.setBalance(newBalance);
            memberAccount.setTotalProfit(newProfit);
            accountService.updateById(memberAccount);
            log.info("更新账户余额成功： " + JSONObject.toJSONString(memberAccount));
        }
        else {
            log.error("*************** 会员入账时会员账户有问题，请注意检查！！！************");
            return;
        }
    }

    /**
     * 生成分润信息
     * @param orderAmount
     * @param profitList
     * @param parentMap
     * @param userMap
     * @return
     */
    private Map<String,PercentAndProfitBean> genProfitInfo(BigDecimal orderAmount, List<ColValueBean> profitList, Map<Integer, String> parentMap, Map<String, User> userMap){
        Map<String,PercentAndProfitBean> profitMap = new HashMap<>();
        for (int i = 0; i < profitList.size(); i++) {
            ColValueBean bean = profitList.get(i);
            String username = parentMap.get(bean.getLevel());
            if(StringUtils.isBlank(username)){
                log.info("分润---未找到level为" + bean.getLevel() + "的上级用户");
                continue;
            }
            User user = userMap.get(username);
            if(user == null){
                log.info("分润---未找到username为" + username + "的上级用户");
                continue;
            }
            //把百分比转换成小数
            BigDecimal divide = BigDecimal.valueOf(bean.getValue()).divide(BigDecimal.valueOf(100),2, RoundingMode.HALF_UP);
            BigDecimal profit = orderAmount.multiply(divide);
            log.info("分润---用户:" + username + ", 分润比例:" + bean.getValue() + ", 分润金额:" + profit);
            profitMap.put(username,new PercentAndProfitBean(bean.getValue(),profit));

        }
        return profitMap;
    }


    @Data
    public static class PercentAndProfitBean{
        Integer precnet;
        BigDecimal profit;

        public PercentAndProfitBean(Integer precnet, BigDecimal profit) {
            this.precnet = precnet;
            this.profit = profit;
        }
    }
}
